﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace Camalot.Common.Extensions {
	public static partial class CamalotCommonExtensions {
		private const RegexOptions REGEX_OPTIONS_DEFAULT = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline;

		#region Regex Extensions 
		public static Match Match (this String s, String pattern, RegexOptions options ) {
			return Regex.Match ( s, pattern, options );
		}

		public static Match Match ( this String s, String pattern ) {
			return Match ( s, pattern, REGEX_OPTIONS_DEFAULT );
		}

		public static bool IsMatch ( this String s, String pattern, RegexOptions options ) {
			return Regex.IsMatch ( s, pattern, options );
		}

		public static bool IsMatch ( this String s, String pattern ) {
			return IsMatch ( s, pattern, REGEX_OPTIONS_DEFAULT );
		}

		public static String REReplace ( this String s, String pattern, String replacement, RegexOptions options ) {
			return Regex.Replace ( s, pattern, replacement, options );
		}

		public static String REReplace ( this String s, String pattern, String replacement ) {
			return REReplace ( s, pattern, replacement, REGEX_OPTIONS_DEFAULT );
		}

		public static String REReplace ( this String s, String pattern, MatchEvaluator evaluator, RegexOptions options ) {
			return Regex.Replace ( s, pattern, evaluator, options );
		}

		public static String REReplace ( this String s, String pattern, MatchEvaluator evaluator) {
			return REReplace ( s, pattern, evaluator, REGEX_OPTIONS_DEFAULT );
		}

		public static String Escape ( this String s ) {
			return Regex.Escape ( s );
		}

		public static String Unescape ( this String s ) {
			return Regex.Unescape ( s );
		}

		public static MatchCollection Matches ( this String s, String pattern, RegexOptions options ) {
			return Regex.Matches ( s, pattern, options );
		}

		public static MatchCollection Matches ( this String s, String pattern ) {
			return Regex.Matches ( s, pattern, REGEX_OPTIONS_DEFAULT );
		}
		#endregion

		public static String With ( this String s, params Object[] args ) {
			return String.Format ( s, args );
		}

		public static StringBuilder ToStringBuilder ( this String s ) {
			return new StringBuilder ( s );
		}


		public static String ToBase64EncodedHash ( this String s ) {
			var md5 = MD5.Create ( );
			var hash = md5.ComputeHash ( s.GetBytes ( ) );
			return Convert.ToBase64String ( hash );
		}

		public static byte[] GetBytes ( this String s, Encoding encoding ) {
			return encoding.GetBytes ( s );
		}

		public static byte[] GetBytes ( this String s ) {
			return GetBytes ( s, Encoding.Default );
		}

		public static String GetString ( this byte[] bytes, Encoding encoding ) {
			return encoding.GetString ( bytes );
		}

		public static String GetString ( this byte[] bytes ) {
			return GetString ( bytes, Encoding.Default );
		}

		public static String ToHex ( this byte[] bytes ) {
			var sb = new StringBuilder ( );
			bytes.ForEach ( b => { sb.Append ( b.ToString ( "X2" ) ); } );
			return sb.ToString ( );
		}

		public static String ToHex ( this byte b ) {
			return b.ToString ( "X2" );
		}
		public static String ToCamelCase ( this object input ) {
			return input.ToString ( ).ToCamelCase ( );
		}
		public static String ToCamelCase ( this String input ) {
			if ( String.IsNullOrWhiteSpace ( input ) ) {
				throw new ArgumentNullException ( "input", "'input' cannot be null or empty." );
			}
			return input.Replace ( input[0], input.ToLower ( )[0] );
		}

		public static String ToPascalCase ( this String input ) {
			if ( String.IsNullOrWhiteSpace ( input ) ) {
				throw new ArgumentNullException ( "input", "'input' cannot be null or empty." );
			}
			return CultureInfo.CurrentUICulture.TextInfo.ToTitleCase ( input );
		}

		public static String[] SplitAndTrim ( this String input, char[] separator, StringSplitOptions options ) {
			var result = new List<String> ( );
			if ( String.IsNullOrWhiteSpace ( input ) ) {
				return result.ToArray ( );
			}
			input.Split ( separator, options ).ForEach ( i => {
				result.Add ( i.Trim ( ) );
			} );
			return result.ToArray ( );
		}

		public static String[] SplitAndTrim ( this String input, char[] separator ) {
			return SplitAndTrim ( input, separator, StringSplitOptions.RemoveEmptyEntries );
		}
	}
}
